import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class HouseRobberIII {
    /**
     * 337. 打家劫舍 III
     *
     * 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口，我们称之为 root 。
     *
     * 除了 root 之外，每栋房子有且只有一个“父“房子与之相连。一番侦察之后，聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ，房屋将自动报警。
     *
     * 给定二叉树的 root 。返回 在不触动警报的情况下 ，小偷能够盗取的最高金额 。
     *
     * 提示：
     *
     * 树的节点数在 [1, 104] 范围内
     * 0 <= Node.val <= 104
     */

    public static void main(String[] args) {

    }

    /**
     * 后序遍历，某树打劫到的最大金额为：偷根节点， 不偷根节点
     * 偷根节点：根节点 + 左右子树的左右子树的和
     * 不偷根节点：左右子树的和
     * 两种情况取最大值
     */

    // 不偷：Max(左孩子不偷，左孩子偷) + Max(又孩子不偷，右孩子偷)
    // root[0] = Math.max(rob(root.left)[0], rob(root.left)[1]) +
    // Math.max(rob(root.right)[0], rob(root.right)[1])
    // 偷：左孩子不偷+ 右孩子不偷 + 当前节点偷
    // root[1] = rob(root.left)[0] + rob(root.right)[0] + root.val;
    public int mySolution(TreeNode root) {
        int[] res = robber(root);
        return Math.max(res[0], res[1]);
    }

    // 状态标记递归
    // 可以使用一个长度为2的数组，记录当前节点偷与不偷所得到的的最大金钱。
    public int[] robber(TreeNode root) {
        // 0: 偷当前节点的最大金额；1: 不偷当前节点的最大金额
        int[] res = new int[2];

        if(root == null){
            return res;
        }

        int[] left = robber(root.left);
        int[] right = robber(root.right);

        res[0] = root.val + left[1] + right[1];
        res[1] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
        return res;
    }
}
